home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / DocShell / ODPrcs.cpp < prev    next >
Encoding:
Text File  |  1996-08-28  |  66.8 KB  |  2,439 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODPrcs.cpp
  3.  
  4.     Contains:    OpenDoc Process runtime functions
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <18>     7/11/96    eeh        1363971: plug memory leaks
  13.         <17>     7/11/96    TJ        Fixed Name of function to check for MacOS 8
  14.         <16>     6/27/96    TJ        Use System define for CFMtype ,and check
  15.                                     for special OpenDoc editors type.
  16.         <15>     6/24/96    NP        10002: Launch time speedups
  17.         <14>     6/23/96    NP        10002: Launch time speedups.
  18.         <13>     6/19/96    NP        10002: Launch time speedups.
  19.         <12>     6/18/96    NP        10002: Launch time speedups. 1303832: Can't
  20.                                     make stationery when part editor is busy.
  21.         <11>     6/14/96    NP        10002: Launch time speedups
  22.         <10>    .06.1996    NP        10002: Launch time fixes, system process.
  23.          <9>    .05.1996    NP        1352438: Added const to parameter in
  24.                                     GetLaunchFailedParams.
  25.          <8>      5/1/96    JA        1213332: Force 68K struct alignment for
  26.                                     'vers' struct.
  27.          <7>    .03.1996    NP        Added comment about lack of error handling
  28.                                     in one routine.
  29.          <6>      3/4/96    TJ        Removed WASSERT.
  30.          <5>      3/1/96    JP        1314798: Made new documents run from temp
  31.                                     file
  32.          <4>      2/6/96    eeh        1318481: change 0 to smCurrentScript
  33.          <3>     1/15/96    TJ        Cleaned Up
  34.          <2>     1/15/96    JA        1269485: Made GetPrefsFileSpec nonstatic.
  35.                                     1303072: Changed criteria for which logo to
  36.                                     show in splash screen.
  37.         <52>    10/31/95    TJ        Made the Splash Screen Non-Modal.#1297413
  38.         <51>    10/26/95    TÇ        1296574 GM:Cannot set default memory
  39.                                     partition size.
  40.         <50>    10/25/95    TÇ        1281409 GM: OpenDoc needs an AboutBox.
  41.         <49>    10/12/95    eeh        1287143: check for open resource forks
  42.         <48>     9/29/95    eeh        1287262: use ShellDef.h
  43.         <47>     9/27/95    TÇ        1287770 GM:Crash when an application is
  44.                                     dragged over the launcher
  45.         <46>     9/27/95    eeh        1284464: use ClipStringToBytes
  46.         <45>      9/8/95    eeh        1268998: get prefs file name from resource
  47.         <44>      9/8/95    CG        #1282518 FB1:Shell moves "bad" aliases from
  48.                                     OD Libs fldr if found.
  49.         <43>      9/8/95    TÇ        1271995 FB1:Get error -35 or -44 opening
  50.                                     stationery off write-protected volume
  51.         <42>      9/5/95    TÇ        1281030 FB1:OpenDoc(tm) corrupts ODF Shared
  52.                                     libraries
  53.         <41>     8/29/95    jpa        Rename Toolbox calls for Univ Hdrs 2.1.
  54.                                     [1279173]
  55.         <40>     8/26/95    TÇ        1269688 FB1:  There is an unnecessary
  56.                                     variable
  57.         <39>     8/22/95    eeh        1278280: include RlShlDef.h
  58.         <38>     8/22/95    eeh        1276821:
  59.                                     kOpenDocShellSignature->kODShellSignature
  60.         <37>     8/16/95    CG        #1274825: Fixed creating stationery for
  61.                                     libs containing multiple editors.
  62.         <36>      8/3/95    TÇ        Remove dependency on obsolete SysPrDef.h
  63.         <35>     6/30/95    TÇ        1251872 BB: Can't open stationery if file
  64.                                     name becomes too long. 1264094 BB:Custom
  65.                                     document size cannot be attached to a
  66.                                     stationery.
  67.         <34>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  68.                                     refcount is wrong in
  69.                                     ODRefCntObjectsomUninit.
  70.         <33>      6/2/95    TÇ        Need to copy resources into newly created
  71.                                     documents.  Completes fix to 4
  72.                                     BB:1233106,1242232, 1254312, 1242283
  73.         <32>     5/25/95    jpa        Removed CODE 7 -- CFM68K b1 doesn't
  74.                                     generate one. [1241078]
  75.         <31>     5/19/95    TÇ        1155852 BB: String constants need to be
  76.                                     moved to resource for Localization, 1235942
  77.                                     Launching the OpenDoc pref file causes a
  78.                                     1000 exception to be thrown, 1249396 (was
  79.                                     BB) OpenDoc shell should serialize
  80.                                     stationery creation.
  81.         <30>     5/10/95    CG        #1243610    BB: Shell should not rely on the
  82.                                     constant kNMAPid.
  83.         <29>      5/7/95    TÇ        1155852 BB: String constants need to be
  84.                                     moved to resource for Localization (mostly
  85.                                     done)
  86.         <28>     4/29/95    TÇ        1216130 BB: Shell should open top draft
  87.                                     upon receipt of open document Apple event
  88.         <27>     4/24/95    eeh        1216915: remove unnecessary param
  89.         <26>     4/24/95    eeh        1240662: send keyODActivateEventCause param
  90.                                     in activate event
  91.         <25>     4/15/95    TÇ        #1216915 DR/BB:Trying to open a document
  92.                                     that is already open causes an error.
  93.         <24>     4/14/95    TÇ        #1186294    DR/BB: Binding for editor also
  94.                                     affect making stationary.
  95.         <23>      4/7/95    eeh        1221297: eventID param to
  96.                                     VerifyAndLaunchDocumentStub
  97.         <22>     3/31/95    TÇ        1223465 BB: Opening and creating documents
  98.                                     under low disk space.  (Creating documents
  99.                                     under low disk space part fixed).
  100.                                     1211032 BB: Invalid Permissions error
  101.                                     opening locked document
  102.         <21>     3/28/95    TÇ        #1151710 BB: Toolbox running out of app
  103.                                     heap.  Document Size dialog implemented.
  104.                                     TestAndVerify now uses SIZE -1 resource in
  105.                                     OpenDoc Preferences if it exists.
  106.         <20>     3/24/95    CG        #1226064: ODTestmain can create stationary.
  107.         <19>     2/24/95    EL        1220392: fix access check bug in last
  108.                                     checkin.
  109.         <18>     2/23/95    EL        1220392: checking read only fails on file
  110.                                     share volumes.
  111.         <17>     2/20/95    TÇ        #1210979 BB: 5-$ Bugs need to be evaluated
  112.                                     and removed from Shell
  113.                                     #1221861 BB: Incomplete AOCE support needs
  114.                                     to be removed from OpenDoc
  115.         <16>     2/13/95    TÇ        1193359: BB: Opening stationery on other
  116.                                     volume causes bus error in Messaging code
  117.                                     1211032: BB: Invalid Permissions Error
  118.                                     opening locked document
  119.         <15>      2/2/95    CG        #1205177:  "Editors" and "OpenDoc
  120.                                     Libraries" folders are being registered
  121.                                     with cfm (PPC only).
  122.         <14>     1/12/95    jpa        Removed HandToHand workaround for bug in
  123.                                     Dagon a1 [1210936]
  124.         <13>      1/6/95    jpa        Added new docstub rsrcs to tables [1196515]
  125.         <12>     12/5/94    jpa        Added GetLaunchFailedParams. [1198075,
  126.                                     1158966]
  127.         <11>    10/24/94    jpa        Took out WASSERTM call & Use BlockMove, not
  128.                                     BlockMoveData [68k].
  129.         <10>    10/12/94    TÇ        68K: use local static version of HandToHand
  130.          <9>    10/10/94    TÇ        #1191470 Need both 68K and PPC document
  131.                                     stub application
  132.          <8>     10/7/94    TÇ        #1191470 Need both 68K and PPC document
  133.                                     stub application
  134.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  135.          <6>      9/8/94    eeh        #1185443: forgot to eliminate strcat and
  136.                                     strcpy.
  137.          <5>      9/8/94    eeh        #1185443.  Lotso changes to separate
  138.                                     document with content from what gets
  139.                                     launched.
  140.          <4>     8/29/94    TÇ        #1158280 OpenDoc™ should not overwrite old
  141.                                     stationery files when creating new ones
  142.          <3>     8/25/94    TÇ        #1183223 Enabled launching of documents in
  143.                                     folders other than that of the OpenDoc
  144.                                     libraries.  Added new call:
  145.                                     VerifyAndLaunchDocument
  146.          <2>     8/22/94    TÇ        #1182448 System Process quits when no
  147.                                     OpenDoc documents are running
  148.          <1>     8/22/94    TÇ        first checked in
  149.          
  150.     To Do:
  151.         Change all uses of ODFileSpec and FSSpecPtr to PlatformFile objects
  152.     In Progress:
  153.         
  154. */
  155.  
  156. #ifndef _EXCEPT_
  157. #include <Except.h>
  158. #endif
  159.  
  160. #ifndef _ODDEBUG_
  161. #include "ODDebug.h"
  162. #endif
  163.  
  164. #ifndef _ODPRCS_
  165. #include "ODPrcs.h"
  166. #endif
  167.  
  168. #ifndef _SHELLDEF_
  169. #include "ShellDef.h"
  170. #endif
  171.  
  172. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  173. #include <StdDefs.xh>
  174. #endif
  175.  
  176. #ifndef SOM_Module_OpenDoc_ODRegistry_defined
  177. #include "ODRgstry.xh"
  178. #endif
  179.  
  180. #ifndef _PLFMFILE_
  181. #include "PlfmFile.h"
  182. #endif
  183.  
  184. #ifndef __ERRORS__
  185. #include <Errors.h>
  186. #endif
  187.  
  188. #ifndef __FOLDERS__
  189. #include <Folders.h>
  190. #endif
  191.  
  192. #ifndef __OSEVENTS__
  193. #include <OSEvents.h>
  194. #endif
  195.  
  196. #ifndef __TOOLUTILS__
  197. #include <ToolUtils.h>
  198. #endif
  199.  
  200. #ifndef __ALIASES__
  201. #include <Aliases.h>
  202. #endif
  203.  
  204. #ifndef __FILES__
  205. #include <Files.h>
  206. #endif
  207.  
  208. #ifndef __RESOURCES__
  209. #include <Resources.h>
  210. #endif
  211.  
  212. #ifndef __DIALOGS__
  213. #include <Dialogs.h>
  214. #endif
  215.  
  216. #ifndef __EVENTS__
  217. #include <Events.h>
  218. #endif
  219.  
  220. #ifndef __APPLEEVENTS__
  221. #include <AppleEvents.h>
  222. #endif
  223.  
  224. #ifndef __GESTALT__
  225. #include <Gestalt.h>
  226. #endif
  227.  
  228. #ifndef __PROCESSES__
  229. #include <Processes.h>
  230. #endif
  231.  
  232. #ifndef __STRING__
  233. #include <String.h>
  234. #endif
  235.  
  236. #ifndef __TEXTUTILS__
  237. #include <TextUtils.h>
  238. #endif
  239.  
  240. #ifndef __STRINGS__
  241. #include <Strings.h>
  242. #endif
  243.  
  244. #ifndef __SCRIPT__
  245. #include <script.h>
  246. #endif
  247.  
  248. #ifndef __FINDER__
  249. #include <Finder.h>
  250. #endif
  251.  
  252. #ifndef _ODMEMORY_
  253. #include <ODMemory.h>
  254. #endif
  255.  
  256. #ifndef _REGISTER_
  257. #include <RegisterFileLibs.h>
  258. #endif
  259.  
  260. #ifndef _ODDPFNS_
  261. #include "ODXDpFns.h"
  262. #endif
  263.  
  264. #ifndef _ERRUTILS_
  265. #include "ErrUtils.h"
  266. #endif
  267.  
  268. #ifndef PREFSFILE_H
  269. #include "PrefsFile.h"
  270. #endif
  271.  
  272. #ifndef _PREFSDEF_
  273. #include "PrefsDef.h"
  274. #endif
  275.  
  276. //==============================================================================
  277. // Constants
  278. //==============================================================================
  279.  
  280. #define kMaxFileNameLen        31
  281.  
  282. #define kNumDocStubRsrcs    11    /* was 12 before CFM68K a3 */
  283.  
  284. const ODULong docStubRsrcType[kNumDocStubRsrcs] = 
  285.     { 
  286.         kDocStubRsrcType,
  287.         kDocStubRsrcType,
  288.         kDocStubRsrcType,
  289.         kDocStubRsrcType,
  290.         kDocStubRsrcType,
  291.         kDocStubRsrcType,
  292.         kDocStubRsrcType,
  293.         kDocStubRsrcType,
  294. //        kDocStubRsrcType,
  295.         kDocStubRsrcType,
  296.         kDocStubRsrcType,
  297.         kSIZERsrcType 
  298.     };
  299.  
  300. const ODULong docStubRsrcID[kNumDocStubRsrcs] = 
  301.     {
  302.         kDocStubRsrcID0,
  303.         kDocStubRsrcID1,
  304.         kDocStubRsrcID2,
  305.         kDocStubRsrcID3,
  306.         kDocStubRsrcID4,
  307.         kDocStubRsrcID5,
  308.         kDocStubRsrcID6,
  309.         kDocStubRsrcID7,
  310.         kDocStubRsrcID8,
  311.         kDocStubRsrcID9,
  312. //        kDocStubRsrcID10,
  313.         kDocStubSIZEID
  314.     };
  315.  
  316. const ODULong copiedRsrcType[kNumDocStubRsrcs] = 
  317.     {
  318.         kcfrgRsrcType,
  319.         kMainCFMType,
  320.         kscszRsrcType,
  321.         kMainCFMType,
  322.         kMainCFMType,
  323.         kCODERsrcType,
  324.         kCODERsrcType,
  325.         kCODERsrcType,
  326. //        kCODERsrcType,
  327.         kMainCFMType,
  328.         kMainCFMType,
  329.         kSIZERsrcType 
  330.     };
  331.  
  332. const ODULong copiedRsrcID[kNumDocStubRsrcs] = 
  333.     {
  334.         kcfrgID,
  335.         kMainCFMPPCID,
  336.         kscszID,
  337.         kMainCFM68KID,
  338.         kMainCFM68KID1,
  339.         kCODEID0,
  340.         kCODEID1,
  341.         kCODEID6,
  342. //        kCODEID7,
  343.         kSOMMemCFM68KID,
  344.         kSOMMemCFMPPCID,
  345.         kSIZEID
  346.     };
  347.  
  348.  
  349. enum
  350. {
  351.     kIsNotSameAsStub        = 0,
  352.     kIsSameAsStub            = 1,
  353.     kIsAlreadyLaunched        = 2
  354. };
  355. typedef ODSShort DocStubType;
  356.  
  357. struct ITextData {
  358.     ScriptCode      theScriptCode;
  359.     LangCode     theLangCode;
  360.     Str255         theText;
  361. };
  362. typedef struct ITextData ITextData;
  363.  
  364. struct EditorUserStringList {
  365.     Str255                     editor;
  366.     ITextData                name;
  367.     EditorUserStringList*     next;
  368. };
  369. typedef struct EditorUserStringList EditorUserStringList;
  370.  
  371. //==============================================================================
  372. // Macros
  373. //==============================================================================
  374.  
  375. #define CHECK(EXPR)    if ((err=(EXPR)) == noErr) ; else return err
  376. #define CHECKR(EXPR,RET)    if ((err=(EXPR)) == noErr) ; else return (RET)
  377.  
  378. #if ODDebug
  379. #define ODPrcsDebugStr(x) DebugStr(c2pstr(x))
  380. #else
  381. #define ODPrcsDebugStr(x)
  382. #endif
  383.  
  384. //==============================================================================
  385. // Function Prototype
  386. //==============================================================================
  387.  
  388. static ODBoolean    IsAProcessRunning(OSType procType, OSType procSignature);
  389.  
  390. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile);
  391. static OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  392.         Str63 fileName);
  393. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  394.         FSSpec* documentSpec,
  395.         DocStubType* isDuplicate, DescType eventID, ODBoolean unsavedDoc);
  396.  
  397. // Document Launching
  398. static OSErr     TestAndUpdate(Handle origRsrc,ResType rtype,short rid);
  399. static OSErr    CreateStationerySeed(FSSpecPtr theDocument, FSSpec* seedFSSPtr);
  400. static size_t    ODXstrlen(const char *s);
  401. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n);
  402. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n);
  403. static char        ODXmemcmp(char* buffer1,char* buffer2,unsigned int len);
  404. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2);
  405. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  406.                                         ODSLong fldrDirID, Str255 pbinaryName);
  407. OSErr GetEditorUserStringPairs(ODSShort resRefNum, EditorUserStringList** pairs, ODUShort* editorCount);
  408. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, ODUShort* editorCount );
  409. static void MoveToTrash( short vRefnum, long dirID, Str255 name );
  410. static ODBoolean IsCertainSystemVersionOrGreater(long systemVersion);
  411.  
  412.  
  413. //==============================================================================
  414. // GetOpenDocBinaryFileSpec
  415. //==============================================================================
  416. #if 0
  417. ODFileSpec    GetOpenDocBinaryFileSpec(char* binaryName)
  418. {
  419.  
  420.     ODFileSpec filespec;
  421.     Str255    pbinaryName;
  422.     ODUShort pbinaryLen = 0;
  423.     
  424.     if (binaryName)
  425.     {
  426.         pbinaryLen = ODXstrlen(binaryName);
  427.         
  428.         if (pbinaryLen>255)
  429.         {
  430.             pbinaryLen = 255;
  431.         }
  432.         
  433.         ODXstrncpy((char*)&(pbinaryName[1]),binaryName,pbinaryLen);
  434.     }
  435.     
  436.     ClipStringToBytes( pbinaryName, pbinaryLen, smCurrentScript );
  437.     
  438.     ODFileSpec odLibsFldrSpec = GetOpenDocLibsFldrSpec();
  439.     ODSLong dirID = GetFldrDirID(odLibsFldrSpec);
  440.     filespec = FindODBinary(odLibsFldrSpec.vRefNum, dirID, pbinaryName);
  441.  
  442.     return filespec;
  443. }
  444.  
  445. //==============================================================================
  446. // FindODBinary
  447. //==============================================================================
  448.  
  449. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  450.                                          ODSLong fldrDirID, Str255 pbinaryName)
  451. {
  452.     CInfoPBRec        CinfoPB;
  453.     Str255            fileName;
  454.     ODFileSpec        fileSpec;
  455.     FSMakeFSSpec(    fldrVRefNum, 
  456.                      fldrDirID, 
  457.                      pbinaryName, &fileSpec);
  458.  
  459.         //check that this is not a bogus folder
  460.     if (fldrDirID != -1)
  461.     {
  462.         memset (&CinfoPB,0,sizeof(CinfoPB));
  463.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&fileName;
  464.         CinfoPB.dirInfo.ioFDirIndex = 1;
  465.         CinfoPB.dirInfo.ioVRefNum = fldrVRefNum;
  466.         CinfoPB.dirInfo.ioDrDirID = fldrDirID;
  467.         
  468.             // Loop through all the files in Library folder
  469.         for(ODSShort i = PBGetCatInfoSync(&CinfoPB); 
  470.                         i == noErr; 
  471.                        i = PBGetCatInfoSync(&CinfoPB))
  472.         {
  473.                 // if this is a folder
  474.             if ((CinfoPB.dirInfo.ioFlAttrib & (1<<4))) 
  475.             {
  476.                 FSSpec fldrSpec;
  477.                 FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  478.                              CinfoPB.hFileInfo.ioFlParID, 
  479.                              fileName, &fldrSpec);
  480.                 OSErr err = RegisterFileLibs(&fldrSpec);
  481.                 fileSpec = FindODBinary(fldrVRefNum, 
  482.                                         CinfoPB.dirInfo.ioDrDirID, 
  483.                                         pbinaryName);
  484.             }
  485.             else
  486.             {
  487.                     // if this is an alias, resolve and do the right thing
  488.                 if ((CinfoPB.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  489.                 {
  490.                     FSSpec    aliasSpec;
  491.                     Boolean    targetIsFolder = kODFalse;
  492.                     Boolean    wasAliased = kODFalse;
  493.                     
  494.                     ODError result = FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  495.                                           CinfoPB.hFileInfo.ioFlParID, 
  496.                                           fileName, &aliasSpec);
  497.                     if (result == noErr)
  498.                     {
  499.                             //resolve alias
  500.                         result = ResolveAliasFile(&aliasSpec, kODTrue, 
  501.                                               &targetIsFolder, &wasAliased);
  502.                         if (result == noErr)
  503.                         {
  504.                             if (aliasSpec.vRefNum != fldrVRefNum)
  505.                                 MoveToTrash( CinfoPB.hFileInfo.ioVRefNum, 
  506.                                              CinfoPB.hFileInfo.ioFlParID, fileName );
  507.                             else
  508.                             {
  509.                                 if (targetIsFolder)
  510.                                 {
  511.                                     OSErr err = RegisterFileLibs(&aliasSpec);
  512.                                     ODSLong dirID = GetFldrDirID(aliasSpec);
  513.                                     FindODBinary(aliasSpec.vRefNum, 
  514.                                                   dirID, pbinaryName);
  515.                                 }
  516.                                 else
  517.                                 {
  518.                                     // if this file's name == pbinaryName, make an FSSpec and return it
  519.                                     if (myEqualPascalStrings(pbinaryName, 
  520.                                                               fileName))
  521.                                         FSMakeFSSpec(aliasSpec.vRefNum, 
  522.                                                       aliasSpec.parID, fileName, 
  523.                                                       &fileSpec);                                    
  524.                                 }
  525.                             }
  526.                         }
  527.                     }
  528.                 }
  529.                 else
  530.                 {
  531.                     // if this file's name == pbinaryName, make an FSSpec and return it
  532.                     if (myEqualPascalStrings(pbinaryName, fileName))
  533.                     {
  534.                         FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  535.                                       CinfoPB.hFileInfo.ioFlParID, 
  536.                                       fileName, &fileSpec);
  537.                     }                            
  538.                 }
  539.             }
  540.  
  541.             CinfoPB.hFileInfo.ioFDirIndex++;
  542.                 //need to do this each time since PBGetCatInfo call returns val here
  543.             CinfoPB.hFileInfo.ioNamePtr = (StringPtr)&fileName;
  544.             CinfoPB.hFileInfo.ioVRefNum = fldrVRefNum;
  545.             CinfoPB.hFileInfo.ioDirID = fldrDirID;  
  546.         }
  547.     }
  548.     return fileSpec;
  549. }
  550.  
  551. //==============================================================================
  552. // GetOpenDocLibsFldrSpec
  553. //==============================================================================
  554.  
  555. OSErr GetOpenDocLibsFldrSpec(ODFileSpec* fileSpec)
  556. {
  557.     long        odDirID, libsFldrDirID;
  558.     short        odVRef, libsFldrVRefNum;
  559.     FileSpec    odFldrSpec;
  560.     Str255        folderName;
  561.     OSErr        result;
  562.  
  563.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  564.  
  565.     if (folderName[0] == 0)
  566.         ODPrcsDebugStr("\pResource Error: OpenDoc Libraries string not found!");
  567.         
  568.     OSErr result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  569.                                 kDontCreateFolder, &libsFldrVRefNum, 
  570.                                 &libsFldrDirID);
  571.     if (result == noErr)
  572.     {
  573.         CInfoPBRec        CinfoPB;
  574.  
  575.         memset (&CinfoPB, 0 ,sizeof(CinfoPB));
  576.  
  577.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  578.         CinfoPB.dirInfo.ioFDirIndex = 0;
  579.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  580.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  581.         
  582.         result = PBGetCatInfoSync(&CinfoPB);
  583.         if (result == noErr)
  584.         {
  585.             odVRef  = CinfoPB.dirInfo.ioVRefNum;
  586.             odDirID = CinfoPB.dirInfo.ioDrParID;
  587.             result = FSMakeFSSpec(odVRef, odDirID, folderName, &odFldrSpec);
  588.         }
  589.     }
  590.     
  591.     *fileSpec = odFldrSpec;
  592.     return result;
  593. }
  594.  
  595. //------------------------------------------------------------------------------
  596. // GetFldrDirID
  597. //------------------------------------------------------------------------------
  598.  
  599. long GetFldrDirID(ODFileSpec theFolderSpec)
  600. {
  601.     long        dirID = -1;
  602.     CInfoPBRec    theParamBlock;
  603.  
  604.     memset (&theParamBlock, 0, sizeof(theParamBlock));
  605.  
  606.     theParamBlock.dirInfo.ioFDirIndex = 0;
  607.     theParamBlock.dirInfo.ioNamePtr = theFolderSpec.name;
  608.     theParamBlock.dirInfo.ioVRefNum = theFolderSpec.vRefNum;
  609.     theParamBlock.dirInfo.ioDrDirID = theFolderSpec.parID;
  610.     ODError result = PBGetCatInfoSync(&theParamBlock);
  611.  
  612.     if (result == noErr && (theParamBlock.hFileInfo.ioFlAttrib & (1<<4))) 
  613.         dirID = theParamBlock.dirInfo.ioDrDirID;
  614.  
  615.     return dirID;
  616. }
  617.  
  618. #ifdef NEEDSYSTEMPROCESS
  619. #define    kODSysProcessType            0x4150504C    // 'APPL' ?should be 'appe' eventually
  620. #define kODSysProcessSignature        0x6F647370    // 'odsp'
  621.  
  622. //==============================================================================
  623. // IsODSysProcessRunning
  624. //==============================================================================
  625.  
  626. ODBoolean    IsODSysProcessRunning()
  627. {
  628.     return IsAProcessRunning(kODSysProcessType,kODSysProcessSignature);
  629.  
  630.     ProcessSerialNumber psn = {0,kNoProcess};
  631.     ProcessInfoRec aProcess;
  632.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  633.     aProcess.processName = NULL;
  634.     aProcess.processAppSpec = NULL;
  635.     
  636.     while (GetNextProcess(&psn) == noErr)
  637.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  638.             if (aProcess.processType == kODSysProcessType &&
  639.                 aProcess.processSignature == kODSysProcessSignature)
  640.                     return true;
  641.     return false;
  642. }
  643. #endif
  644. #endif /* 0 */
  645. //==============================================================================
  646. // AreODDocumentsRunning
  647. //==============================================================================
  648.  
  649. ODBoolean    AreODDocumentsRunning()
  650. {
  651.     ProcessSerialNumber    psn = {0, kNoProcess};
  652.     ProcessInfoRec        aProcess;
  653.     ODBoolean            result = kODFalse;
  654.     PlatformFile*        processFile = new PlatformFile;
  655.     FSSpec                processAppSpec;
  656.  
  657.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  658.     aProcess.processName = NULL;
  659.     aProcess.processAppSpec = &processAppSpec;
  660.     
  661.     while (GetNextProcess(&psn) == noErr)
  662.     {
  663.         if (GetProcessInformation(&psn, &aProcess) == noErr)
  664. //            if (aProcess.processType != 'APPL' &&
  665. //                aProcess.processSignature == kODShellSignature)
  666. //                    return true;
  667.         {
  668.             processFile->Specify(aProcess.processAppSpec);
  669.             if (processFile->IsOpenDocDocument())
  670.             {
  671.                 result = kODTrue;
  672.                 break;
  673.             }
  674.         }
  675.         else
  676.             ODPrcsDebugStr("AreODDocumentsRunning: GetProcessInformation failed!");
  677.     }
  678.  
  679.     delete processFile;
  680.     return result;
  681. }
  682.  
  683. //==============================================================================
  684. // FileIsReadOnly
  685. //==============================================================================
  686.  
  687. OSErr FileIsReadOnly(ODFileSpec* fs, ODBoolean* result)
  688. {
  689. // Note: copied from PlatformFile::IsLocked.  OpenDoc™ DOES NOT link in Util.lib. -TÇ
  690.  
  691.     CInfoPBRec    pbBlock;
  692.     *result = kODFalse;
  693.     OSErr err = noErr;
  694.  
  695.     // Check to see whether the volume is locked
  696.  
  697.     // Eric's original code with slight modifications.
  698.     // Appears to be needed in the case of a locked floppy. -TÇ
  699.     HParamBlockRec pb;
  700.     pb.volumeParam.ioCompletion = kODNULL;
  701.     pb.volumeParam.ioNamePtr = kODNULL;
  702.     pb.volumeParam.ioVRefNum = fs->vRefNum;
  703.     pb.volumeParam.ioVolIndex = 0;
  704.  
  705.     err = PBHGetVInfoSync(&pb);
  706.     if (err) return err;
  707.  
  708.     *result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  709.     
  710.     // Check to see whether the directory is locked
  711.     if (*result == kODFalse) {
  712.         // first assume it is a file share volume
  713.         HParamBlockRec    paramBlk;
  714.         paramBlk.accessParam.ioCompletion = kODNULL;
  715.         paramBlk.accessParam.ioNamePtr = kODNULL;
  716.         paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  717.         paramBlk.accessParam.ioDirID = fs->parID;
  718.         paramBlk.accessParam.ioACAccess = 0;
  719.         err = PBHGetDirAccessSync(¶mBlk);
  720.         
  721.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  722.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  723.                 *result = kODTrue;
  724.         }
  725.         else if (err == paramErr) { /* it is not file share, look at directory */
  726.             pbBlock.dirInfo.ioCompletion = kODNULL;
  727.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  728.             pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  729.             pbBlock.dirInfo.ioFDirIndex = -1;
  730.             pbBlock.dirInfo.ioDrDirID = fs->parID;
  731.             pbBlock.dirInfo.ioFlAttrib = 0;
  732.             err = PBGetCatInfoSync(&pbBlock);
  733.             if (err) return err;
  734.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  735.                 *result = kODTrue;            
  736.         }
  737.         else
  738.             return err;
  739.     }
  740.  
  741.     // Check to see whether the file is locked
  742.     if (*result == kODFalse) {    
  743.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  744.         pbBlock.hFileInfo.ioFDirIndex = 0;
  745.         pbBlock.hFileInfo.ioNamePtr = fs->name;
  746.         pbBlock.hFileInfo.ioVRefNum = fs->vRefNum;
  747.         pbBlock.hFileInfo.ioDirID = fs->parID;
  748.         
  749.         err =  PBGetCatInfoSync(&pbBlock);
  750.         if (err) return err;
  751.  
  752.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  753.             *result = kODTrue;
  754.     }
  755.             
  756.     return noErr;
  757. }
  758.  
  759. //==============================================================================
  760. // GetVolumeWritableSpace
  761. //==============================================================================
  762.  
  763. ODULong    GetVolumeWritableSpace(ODFileSpec* fs, ODULong* error)
  764. {    
  765.     ODULong err = noErr;
  766.     HParamBlockRec    paramBlk;
  767.     ODBoolean        writable = kODFalse;
  768.     
  769.     if (error == kODNULL)
  770.         error = &err;
  771.         
  772.     paramBlk.accessParam.ioCompletion = kODNULL;
  773.     paramBlk.accessParam.ioNamePtr = kODNULL;
  774.     paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  775.     paramBlk.accessParam.ioDirID = fs->parID;
  776.     paramBlk.accessParam.ioACAccess = 0;
  777.     *error = PBHGetDirAccessSync(¶mBlk);
  778.     
  779.     if (*error == noErr) {        /* it is a file share volume, look at the access right */
  780.         if (paramBlk.accessParam.ioACAccess & 0x04000000)
  781.             writable = kODTrue;
  782.     }
  783.     else if (*error == paramErr) { /* it is not file share, look at directory */
  784.         CInfoPBRec    pbBlock;
  785.         pbBlock.dirInfo.ioCompletion = kODNULL;
  786.         pbBlock.dirInfo.ioNamePtr = kODNULL;
  787.         pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  788.         pbBlock.dirInfo.ioFDirIndex = -1;
  789.         pbBlock.dirInfo.ioDrDirID = fs->parID;
  790.         pbBlock.dirInfo.ioFlAttrib = 0;
  791.         *error = PBGetCatInfoSync(&pbBlock);
  792.         if (*error) return 0;
  793.         
  794.         if (!(pbBlock.dirInfo.ioFlAttrib & 1))
  795.             writable = kODTrue;
  796.     }
  797.     else
  798.          return 0;
  799.  
  800.     if (writable != kODFalse) {
  801.         // how much space on this writable volume?
  802.         HParamBlockRec hpb;
  803.         hpb.volumeParam.ioVolIndex = 0;
  804.         hpb.volumeParam.ioNamePtr = kODNULL;
  805.         hpb.volumeParam.ioVRefNum = fs->vRefNum;
  806.         
  807.         *error = PBHGetVInfoSync(&hpb);
  808.         if (*error) return 0;
  809.         
  810.         if (!(hpb.volumeParam.ioVAtrb & 0x80))
  811.             return ((hpb.volumeParam.ioVFrBlk * hpb.volumeParam.ioVAlBlkSiz) / 1024);
  812.         // Appears to be needed in the case of a locked floppy. -TÇ
  813.     }    
  814.  
  815.     *error = kODErrDirectoryNotHaveWriteAccess;
  816.     return 0;
  817. }
  818.  
  819. //==============================================================================
  820. // GetDescFSSpec
  821. //==============================================================================
  822.  
  823. OSErr
  824. GetDescFSSpec(AEDesc *desc, FSSpec &spec)
  825. {
  826.     AEDesc resultDesc;
  827.     OSErr err = AECoerceDesc(desc, typeFSS, &resultDesc);
  828.     if (err) return err;
  829.     spec = **(FSSpec**)(resultDesc.dataHandle);
  830.     AEDisposeDesc(&resultDesc);
  831.     return noErr;
  832. }
  833.  
  834.  
  835. //==============================================================================
  836. // MakeDocumentStub
  837. //==============================================================================
  838.  
  839. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile)
  840. {
  841.     // Don't modify this one!
  842.     char* nmSeed = isFile? "ODShellTempFile" : "ODShellTempFolder";
  843.     ODXstrncpy((char*)name, nmSeed, ODXstrlen(nmSeed)+1);
  844.  
  845.     char theNum[10];
  846.     NumToString(seed, (StringPtr)theNum); 
  847. //    WASSERT(theNum[0] <= 5);
  848.     p2cstr((StringPtr)theNum);
  849.  
  850.     ODXstrncat((char*)name, theNum, ODXstrlen(theNum)+1);
  851.     c2pstr((char *)name);
  852. }
  853.  
  854. OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  855.         Str63 fileName)
  856. {
  857.     Str255        myName;
  858.     ODSLong    myDirID;
  859.     ODSShort    myVRef;
  860.  
  861.     FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &myVRef, &myDirID);
  862.  
  863.     OSErr err;
  864.     short limit = 100;
  865.     short seed = 1;
  866.     while (--limit)
  867.     {
  868.         CreateTempName(seed++, myName, kODFalse);
  869.         long createdDirID;
  870.         err = DirCreate(myVRef, myDirID, myName,
  871.                 &createdDirID);
  872.         if (err == noErr)
  873.         {
  874.             FSMakeFSSpec(myVRef, createdDirID, fileName, result);
  875.             return noErr;
  876.         }
  877.     }
  878.     return err;
  879. }
  880.  
  881. //------------------------------------------------------------------------------
  882. // GetLaunchFailedParams
  883. //------------------------------------------------------------------------------
  884.  
  885. void GetLaunchFailedParams(const AppleEvent *ae, long &launchError,
  886.                             ProcessSerialNumber *psn, Str255 appName,
  887.                             Str255 libName)
  888. {
  889.     OSErr err;
  890.     DescType type;
  891.     Size size;
  892.     
  893.     err= AEGetParamPtr(ae, keyErrorNumber, typeLongInteger, &type,
  894.                             &launchError, sizeof(launchError), &size);
  895.     if (err)
  896.         launchError = err;
  897.         
  898.     if (psn!=NULL) {
  899.         psn->lowLongOfPSN = 0;
  900.         psn->highLongOfPSN = 0;
  901.         (void) AEGetParamPtr(ae,keyProcessSerialNumber,typeProcessSerialNumber,&type,
  902.                             psn,sizeof(*psn), &size);
  903.     }
  904.     
  905.     err= AEGetParamPtr(ae, 'APPL', typeChar, &type, &appName[1], 255, &size);
  906.     appName[0] = err ?0 :size;
  907.     
  908.     err= AEGetParamPtr(ae, 'LIBN', typeChar, &type, &libName[1], 255, &size);
  909.     libName[0] = err ?0 :size;
  910. }
  911.  
  912. //------------------------------------------------------------------------------
  913. // MakeDocumentStub
  914. //------------------------------------------------------------------------------
  915.  
  916. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  917.                                 FSSpec* documentSpec,
  918.                                 DocStubType* isDuplicate,
  919.                                 DescType eventID,
  920.                                 ODBoolean unsavedDoc)
  921. {
  922.     OSErr err;
  923.     
  924.     FSSpec documentFSSpec;
  925.     CHECK(GetDescFSSpec(document, documentFSSpec));
  926.     *documentSpec = documentFSSpec;
  927.  
  928.     FInfo documentFInfo;
  929.     err= FSpGetFInfo(&documentFSSpec, &documentFInfo);
  930.     if (err) return err;
  931.  
  932.      // DON'T WORRY ABOUT OPEN LIBRARIES    
  933.     if (documentFInfo.fdType != kCFragLibraryFileType &&
  934.         documentFInfo.fdType != kODSpecialEditorType)
  935.     {
  936.         // BUT DON'T RELAUNCH OPEN DOCUMENTS
  937.         if (WasLaunchedThenActivate(documentSpec, eventID, err ))
  938.         {
  939.             *isDuplicate = kIsAlreadyLaunched;
  940.             return err;
  941.         }
  942.     }
  943.  
  944.     // if it's a read-only file OR if it's on a server OR if it's stationery,
  945.     // OR it's unsaved (i.e. a New document)
  946.     // make a new one.
  947.     
  948.     ODBoolean makeNewOne;
  949.     err = FileIsReadOnly(&documentFSSpec, &makeNewOne);
  950.     if (err) return err;
  951.     makeNewOne = makeNewOne || (((documentFInfo.fdFlags)&kIsStationary)!=0) ||
  952.         (documentFInfo.fdCreator != kODShellSignature) || unsavedDoc;
  953.     if (!makeNewOne || 
  954.         documentFInfo.fdType == kCFragLibraryFileType ||
  955.         documentFInfo.fdType == kODSpecialEditorType)
  956.     {
  957.         *documentStub = documentFSSpec;
  958.         *isDuplicate = kIsSameAsStub;
  959.         return noErr;
  960.     }
  961.     
  962.     // if we get here we need a new file....
  963.     *isDuplicate = kIsNotSameAsStub;
  964.  
  965.     FSSpec newFileSpec;
  966.     err = CreateUniqueTmpFolderForFile(&newFileSpec, documentFSSpec.name);    
  967.     if (err) return err;
  968.  
  969.     err = FSpCreate( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  970.             smSystemScript );
  971.     FSpCreateResFile( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  972.             smSystemScript );
  973.     if (!err)
  974.         *documentStub = newFileSpec;
  975.  
  976.     // Need to copy over custom SIZE 0 & 1 resource for proper custom heapsize behaviour
  977.     // for readonly documents and documents newly created from stationery.
  978.     
  979.     short theCurResFile = CurResFile();
  980.     short docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdPerm);
  981.     
  982.     if (docResFile != -1)
  983.     {
  984.         ODHandle size0 = kODNULL;
  985.         size0 = Get1Resource(kSIZERsrcType, 0);
  986.         if (size0)
  987.             DetachResource(size0);
  988.         ODHandle size1 = kODNULL;
  989.         size1 = Get1Resource(kSIZERsrcType, 1);
  990.         if (size1)
  991.             DetachResource(size1);
  992.         CloseResFile( docResFile );
  993.         
  994.         short stubResFile = FSpOpenResFile((const FSSpec *)&newFileSpec,fsRdWrPerm);
  995.         if (size0)
  996.             err = TestAndUpdate(size0,kSIZERsrcType,0);
  997.         if (!err && size1)
  998.             err = TestAndUpdate(size1,kSIZERsrcType,1);
  999.         CloseResFile( stubResFile );
  1000.         
  1001.         if (size0)
  1002.             DisposeHandle(size0);
  1003.         if (size1)
  1004.             DisposeHandle(size1);
  1005.  
  1006.         UseResFile(theCurResFile);
  1007.     }
  1008.  
  1009.     return err;
  1010. }
  1011.  
  1012. //==============================================================================
  1013. // WasLaunchedThenActivate
  1014. //==============================================================================
  1015.  
  1016.  
  1017. ODBoolean    WasLaunchedThenActivate(
  1018.                         FSSpec* fileSpec,
  1019.                         DescType eventID,
  1020.                         OSErr & err)
  1021. {
  1022.     // check if the file we want to open is already open by someone on this machine
  1023.     ODULong        refNumCount = 0;
  1024.     RefNumPtr    refNums = kODNULL;
  1025.  
  1026.     CHECKR(GetLocalPaths(fileSpec, kDataFork, &refNumCount, &refNums), kODFalse);
  1027.     DisposePtr((Ptr) refNums);
  1028.     refNums = kODNULL;
  1029.     ODBoolean refnumForResFork = refNumCount == 0;    // don't count on
  1030.                                                     // refnumForResFork in the
  1031.                                                     // case where
  1032.                                                     // we're returning false
  1033.     if ( refnumForResFork )        // try again with the resource fork
  1034.     {
  1035.         CHECKR(GetLocalPaths(fileSpec, kResourceFork, &refNumCount, &refNums),
  1036.                 kODFalse);
  1037.         DisposePtr((Ptr) refNums);
  1038.         if (refNumCount == 0)
  1039.             return kODFalse;
  1040.     }
  1041.         
  1042.     AppleEvent    activateEvent, reply;
  1043.     AEDesc        addressDesc = {typeNull, kODNULL};
  1044.     ProcessSerialNumber psn = {0,kNoProcess};
  1045.     ProcessInfoRec aProcess;
  1046.     
  1047. //    DisposePtr((Ptr) refNums);        // <eeh> why doesn't this come before the return above?
  1048.     // create the activate event
  1049.     CHECKR(AECreateAppleEvent(kAEOpenDocSuite, kODActivateEvent, &addressDesc, 
  1050.                 kAutoGenerateReturnID, kAnyTransactionID, &activateEvent)
  1051.             , kODTrue);
  1052.  
  1053.     err = AEPutParamPtr(&activateEvent, keyDirectObject, typeFSS, 
  1054.                                         (Ptr) fileSpec, sizeof(*fileSpec));
  1055.     if (err != noErr)
  1056.     {
  1057.         AEDisposeDesc(&activateEvent);
  1058.         return kODTrue;
  1059.     }
  1060.  
  1061.     err = AEPutParamPtr(&activateEvent, keyODActivateEventCause, typeType, 
  1062.                                         (Ptr)&eventID, sizeof(eventID));
  1063.     if (err != noErr)
  1064.     {
  1065.         AEDisposeDesc(&activateEvent);
  1066.         return kODTrue;
  1067.     }
  1068.     
  1069.     if ( refnumForResFork )
  1070.     {
  1071.         err = AEPutParamPtr( &activateEvent, keyODRefnumFromResource,
  1072.                 typeBoolean, (Ptr)&refnumForResFork,
  1073.                 sizeof(refnumForResFork) );
  1074.         if (err != noErr)
  1075.         {
  1076.             AEDisposeDesc(&activateEvent);
  1077.             return kODTrue;
  1078.         }
  1079.     }
  1080.  
  1081.     // send the activate event to all OpenDoc processes
  1082.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  1083.     aProcess.processName = kODNULL;
  1084.     aProcess.processAppSpec = kODNULL;
  1085.     
  1086.     while (GetNextProcess(&psn) == noErr)
  1087.         if (GetProcessInformation(&psn, &aProcess) == noErr)
  1088.             if (aProcess.processType != 'APPL' &&
  1089.                 aProcess.processSignature == kODShellSignature)
  1090.             {
  1091.                 CHECKR(
  1092.                     AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(psn),
  1093.                                  &addressDesc)
  1094.                     , kODTrue);
  1095.  
  1096.                 CHECKR(AEPutAttributeDesc(&activateEvent, keyAddressAttr, &addressDesc)
  1097.                         , kODTrue);
  1098.                 CHECKR(AESend(&activateEvent, &reply, kAENoReply, kAENormalPriority,
  1099.                                 kAEDefaultTimeout, kODNULL, kODNULL)
  1100.                         , kODTrue);
  1101.                 // this shouldn't error since the handler always returns noErr
  1102.                 // ASSERT that reply == {typeNull, 0}
  1103.  
  1104.                 InitCursor();
  1105.  
  1106.                 CHECKR(AEDisposeDesc(&addressDesc), kODTrue);
  1107.             }
  1108.     err = AEDisposeDesc(&activateEvent);
  1109.     return kODTrue;
  1110. }
  1111.  
  1112. //------------------------------------------------------------------------------
  1113. // VerifyAndLaunchDocumentStub
  1114. //------------------------------------------------------------------------------
  1115.  
  1116. OSErr VerifyAndLaunchDocumentStub(AEDesc *theDocument, AEDescList* otherParams,
  1117.         ProcessSerialNumber *psn, DescType eventID, FSSpec* seedFSSPtr, 
  1118.         ODBoolean unsavedDoc)
  1119. {
  1120.     // if the document isn't local or can't be written to, make a local stub
  1121.     // in temp items folder.
  1122.     
  1123.     FSSpec documentStub;
  1124.     FSSpec documentSpec;
  1125.     DocStubType isDuplicate;
  1126.     OSErr err;
  1127.  
  1128.     err = MakeDocumentStub(theDocument, &documentStub, &documentSpec,
  1129.                             &isDuplicate, eventID, unsavedDoc);
  1130.     if (isDuplicate == kIsAlreadyLaunched)
  1131.         return err;
  1132.         
  1133.     if (!err)
  1134.     {
  1135.         if (unsavedDoc) {
  1136.             // If this doesn't work, will be tried again the next time doc is
  1137.             //    launched.
  1138.             err = VerifyDocumentStub(&documentSpec, kODNULL);
  1139.         }
  1140.         err = VerifyDocumentStub(&documentStub, seedFSSPtr);
  1141.         if (!err && documentStub.name[0]!=0) {
  1142.             // need to get the alias here rather than coerce in LaunchDocument,
  1143.             // as the AEM can't coerce FSS->Alias, at least when AOCE docs are
  1144.             // involved.
  1145.             // $Opt: Remove alias stuff if unnecessary for non AOCE docs.
  1146.             AEDesc theAlias;
  1147.             OSErr aliasErr = 1;            // so won't pass test below unless set
  1148.             if (isDuplicate == kIsSameAsStub)
  1149.                 aliasErr = NewAliasMinimal(&documentStub,
  1150.                         (AliasHandle *)&theAlias.dataHandle);
  1151.     
  1152.             if (seedFSSPtr == kODNULL ||
  1153.                 seedFSSPtr->vRefNum != documentStub.vRefNum ||
  1154.                 seedFSSPtr->parID != documentStub.parID ||
  1155.                 seedFSSPtr->name[0] != documentStub.name[0])
  1156.             {
  1157.                 if (!aliasErr) {
  1158.                     theAlias.descriptorType = typeAlias;
  1159.                     err= LaunchDocumentStub(theDocument, &documentStub, &theAlias,
  1160.                         otherParams, psn, eventID);
  1161.                     AEDisposeDesc(&theAlias);
  1162.                 } else
  1163.                     err= LaunchDocumentStub(theDocument, &documentStub, kODNULL,
  1164.                         otherParams, psn, eventID);
  1165.             }
  1166.         }
  1167.     }
  1168.     return err;
  1169. }
  1170.  
  1171. //------------------------------------------------------------------------------
  1172. // GetPrefsFileSpec
  1173. //------------------------------------------------------------------------------
  1174.  
  1175. OSErr GetPrefsFileSpec(ODFileSpec* prefFileSpec)
  1176. {
  1177.     CInfoPBRec        pb;
  1178.     memset (&pb,0,sizeof(pb));
  1179.  
  1180.     FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, 
  1181.                             &pb.dirInfo.ioVRefNum, &pb.dirInfo.ioDrDirID);
  1182.     StringHandle prefsFileName = GetString( kSHLPrefsFileNameResID );
  1183.  
  1184.     if ( !prefsFileName )
  1185.         ODPrcsDebugStr( "couldn't find kSHLPrefsFileNameResID str resource" );
  1186.  
  1187.     StringHandle prefsFolderName = GetString( kSHLPrefsFolderNameResID );
  1188.  
  1189.     if ( !prefsFolderName )
  1190.         ODPrcsDebugStr( "couldn't find kSHLPrefsFolderNameResID str resource" );
  1191.  
  1192.     //ODGetString(prefFolderName,kODPrefsFolderNameStrID);
  1193.  
  1194.     Str63 name; //must be an array because sizeof depends on it below
  1195.     //CopyPascalString(name,*prefsFolderName);
  1196.     BlockMove(*prefsFolderName,name,sizeof(name));    
  1197.     
  1198.     pb.dirInfo.ioNamePtr = name;
  1199.     pb.dirInfo.ioFDirIndex = 0;
  1200.     OSErr result = PBGetCatInfoSync( &pb );
  1201.     if (result == noErr)
  1202.     {
  1203.         if( pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias ) {
  1204.             FSSpec spec;
  1205.             ODBoolean targetIsFolder, wasAliased;
  1206.             FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,name, &spec);
  1207.             result =  ResolveAliasFile(&spec, kODTrue, &targetIsFolder, &wasAliased);
  1208.             if (result == noErr)
  1209.             {
  1210.                 if( !targetIsFolder )
  1211.                     result = dirNFErr;
  1212.                 // Now get dir ID of target folder:
  1213.                 pb.dirInfo.ioNamePtr = spec.name;
  1214.                 pb.dirInfo.ioFDirIndex = 0;
  1215.                 pb.dirInfo.ioVRefNum = spec.vRefNum;
  1216.                 pb.dirInfo.ioDrDirID = spec.parID;
  1217.                 result = PBGetCatInfoSync( &pb );
  1218.             }
  1219.         }
  1220.     
  1221.         if (result == noErr)
  1222.         {
  1223.             FSMakeFSSpec(pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID, *prefsFileName, prefFileSpec);
  1224.             ReleaseResource( (Handle)prefsFileName );
  1225.             ReleaseResource( (Handle)prefsFolderName );
  1226.         }
  1227.     }
  1228.     return result;
  1229. }
  1230.  
  1231. //------------------------------------------------------------------------------
  1232. // GetPrefSizeResource
  1233. //------------------------------------------------------------------------------
  1234.  
  1235. static ODHandle GetPrefSizeResource()
  1236. {
  1237.     ODHandle prefSize = kODNULL;
  1238.     short theCurResFile = CurResFile();
  1239.     // Code partially copied from Prefs.cpp, should probably call a common util function
  1240.     ODFileSpec        prefFileSpec;
  1241.     OSErr result = GetPrefsFileSpec(&prefFileSpec);
  1242.     if (result == noErr)
  1243.     {
  1244.         ODSShort         prefResFile;
  1245.         prefResFile = FSpOpenResFile((const FSSpec *)&prefFileSpec,fsRdPerm);
  1246.         
  1247.         if (prefResFile != -1)
  1248.         {
  1249.             prefSize = Get1Resource(kSIZERsrcType, kSIZEID);
  1250.             if (prefSize)
  1251.                 DetachResource(prefSize);
  1252.             CloseResFile( prefResFile );
  1253.             UseResFile(theCurResFile);
  1254.         }
  1255.     }
  1256.     return prefSize;
  1257. }
  1258.  
  1259. //------------------------------------------------------------------------------
  1260. // TestAndUpdate
  1261. //------------------------------------------------------------------------------
  1262.  
  1263. // Check the doc's resource against the original copy.
  1264. static OSErr TestAndUpdate(Handle origRsrc,ResType rtype,short rid)
  1265. {
  1266.     // For SIZE-1, we need to check to see if there is an override in OpenDoc Prefs
  1267.     OSErr result = noErr;
  1268.     ODHandle prefSize = kODNULL;
  1269.     if (rtype == kSIZERsrcType && rid == kSIZEID)
  1270.     {
  1271.         prefSize = GetPrefSizeResource();
  1272.         if (prefSize != kODNULL)
  1273.             origRsrc = prefSize;
  1274.     }
  1275.     
  1276.     Handle docRsrc = Get1Resource(rtype, rid);
  1277.     
  1278.     do {            // just to have something to break out of...
  1279.         if (docRsrc) 
  1280.         {
  1281.             // Doc has resource. Compare data and possibly update:
  1282.             Size origSize = GetHandleSize(origRsrc);
  1283.             if (GetHandleSize(docRsrc)!=origSize
  1284.                                 || ODXmemcmp(*origRsrc,*docRsrc,origSize)!=0) 
  1285.             {
  1286.                 SetHandleSize(docRsrc, origSize);            // Rsrc contents are different
  1287.                 if ( (result = MemError()) != noErr )
  1288.                     break;
  1289.                 BlockMove(*origRsrc,*docRsrc,origSize);        // so copy over the original data
  1290.                 ChangedResource(docRsrc);
  1291.                 result = ResError();                        // Something bad happened...
  1292.                 break;
  1293.             }
  1294.             else
  1295.                 break;
  1296.         } 
  1297.         else 
  1298.         {
  1299.             result = ResError();
  1300.             if (result!=noErr && result!=resNotFound)
  1301.                 break;
  1302.             
  1303.             // No such rsrc in document, so add one:
  1304.             docRsrc = origRsrc;
  1305.             if ( (result = HandToHand(&docRsrc)) != noErr )
  1306.                 break;
  1307.             AddResource(docRsrc,rtype,rid,nil);
  1308.             result = ResError();
  1309.         }
  1310.     } while ( false );
  1311.     if (prefSize != kODNULL)
  1312.         DisposeHandle(prefSize);
  1313.     return result;
  1314. }
  1315.  
  1316.  
  1317. //==============================================================================
  1318. // VerifyDocument
  1319. //==============================================================================
  1320.  
  1321. OSErr VerifyDocumentStub(FSSpec *theStub, FSSpec* seedFSSPtr)
  1322. {
  1323. // VerifyDocumentStub precondition: theStub is writable or it is an OpenDoc Editor
  1324. // All resources are verified on both 68K & PPC.
  1325. // if the FSSpec passed in is an OpenDoc Editor
  1326. // then we create a stationery pad seed file and
  1327. //  munge the FSSpec to point to it instead
  1328.  
  1329.     // First, grab my original copies of the rsrcs to be stuffed into the document:
  1330.     Handle origRsrc[kNumDocStubRsrcs] = { kODNULL, kODNULL, kODNULL, kODNULL };
  1331.         
  1332.     OSErr err = noErr;
  1333.     ODUShort i = 0;
  1334.     do {
  1335.         origRsrc[i] = GetResource(docStubRsrcType[i],docStubRsrcID[i]);
  1336.     } while (origRsrc[i] != kODNULL && ++i<kNumDocStubRsrcs);
  1337.         
  1338.     if (i != kNumDocStubRsrcs)
  1339.         return ResError() ? ResError() :resNotFound;        // Some resource is missing
  1340.  
  1341.     // If we are opening a shared library, create a stationery seed file:
  1342.     FInfo finderInfo;
  1343.     FSpGetFInfo(theStub,&finderInfo);
  1344.     if (finderInfo.fdType == kCFragLibraryFileType ||
  1345.         finderInfo.fdType == kODSpecialEditorType)
  1346.     {
  1347.         CHECK(CreateStationerySeed(theStub, seedFSSPtr));
  1348.     } 
  1349.     else if (finderInfo.fdType == kPrefFileType) 
  1350.     {
  1351.         theStub->name[0] = 0;
  1352.         Str255    errorString;
  1353.         GetIndString(errorString, kODXLibsFldrStrID,
  1354.                         kODXTriedToOpenPrefsStrIndex);
  1355.         ReportErrorGeneric(errorString);
  1356. #if 0
  1357.         Str255 s;
  1358.         GetIndString(s, kODXLibsFldrStrID, 2); // EASTER EGG!
  1359.         if (s[0])
  1360.         {
  1361.             ParamText(s,"\p","\p","\p");
  1362.             NoteAlert(2001,NULL);
  1363.         }
  1364. #endif /* 0 */
  1365.         return noErr;
  1366.     }
  1367.     else if (finderInfo.fdType == 'APPL')
  1368.     {
  1369.         theStub->name[0] = 0;
  1370.     }
  1371.     
  1372.  
  1373.     if (theStub->name[0] == 0)  // File was non-Editor shared library, or unable to create stub
  1374.         return noErr;
  1375.         
  1376.     // Now open (or create) the document's resource fork:
  1377.     short theCurResFile = CurResFile();
  1378.     short docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1379.     if ((err = ResError()) != noErr)
  1380.     {
  1381.         // Need to create resource fork if there is none:
  1382.         if (err == eofErr)
  1383.         {
  1384.             // If other than eofErr, something's wrong
  1385.             // would have expected fnfErr. 
  1386.             // if the create fails, we might try settting the eof to 0.
  1387.             // and trying the create again
  1388.             FSpCreateResFile(theStub,finderInfo.fdCreator,finderInfo.fdType,smSystemScript);
  1389.             if ((err = ResError()) == noErr)
  1390.             {
  1391.                 docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1392.                 err = ResError();
  1393.             }
  1394.         }
  1395.         if (err != noErr)
  1396.             return err;
  1397.     }
  1398.  
  1399.     // Finally, verify, add, and/or update the document resources:
  1400.     for (i = 0; i<kNumDocStubRsrcs && err==noErr; ++i)
  1401.     {
  1402.         err = TestAndUpdate(origRsrc[i],copiedRsrcType[i],copiedRsrcID[i]);
  1403.     }
  1404.     
  1405.     // Clean up our toys and go home:
  1406.     CloseResFile(docRefNum);
  1407.     if (!err)
  1408.         err= ResError();
  1409.         
  1410.     UseResFile(theCurResFile);
  1411.     
  1412.     return err;
  1413. }
  1414.  
  1415.  
  1416. //==============================================================================
  1417. // CreateStationerySeed
  1418. //==============================================================================
  1419.  
  1420. static OSErr CreateStationerySeed(FSSpec *theDocument, FSSpec* seedFSSPtr)
  1421. {
  1422.     // note that coming in, theDocument is actually the Editor library;
  1423.     // going out, theDocument is the newly created Stationery Seed
  1424.     // seedFSSPtr is used if already set (name[0]≠0), else it is filled in.
  1425.     // IF seedFSSPtr is NOT filled in, then theDocument name is set to null.
  1426.  
  1427.     OSErr err = noErr;
  1428.     ODEditor   editorID = kODNULL;
  1429.     EditorUserStringList*    editorUsrStrgPairs = kODNULL;
  1430.     ODUShort editorCount = 0;
  1431.     EditorUserStringList* pair = kODNULL;
  1432.     
  1433. // First, read in the editorUserString NMAP from the Editor library
  1434.     short saveResFile = CurResFile();
  1435.     short resRefNum = FSpOpenResFile(theDocument,fsRdPerm);
  1436.     if ((err = ResError()) != noErr)
  1437.         return err;
  1438.     
  1439.     err = GetEditorUserStringPairs(resRefNum, &editorUsrStrgPairs, &editorCount);
  1440.     CloseResFile(resRefNum);
  1441.     UseResFile(saveResFile);
  1442.     if (err != noErr)
  1443.         return err;
  1444.  
  1445.     if (editorCount == 0)
  1446.     {
  1447.         theDocument->name[0] = 0;
  1448.         return noErr;
  1449.     }
  1450.     
  1451. // Loop through the list of editor/editorUserString pairs 
  1452. //    (libraries may contain more than one editor)
  1453.  
  1454.     for (pair = editorUsrStrgPairs;
  1455.             pair;
  1456.             pair = pair->next)
  1457.     {
  1458.         long length = pair->editor[0];
  1459.         Handle editor = NewHandleClear(1+length);
  1460.         if (MemError())
  1461.             return MemError();
  1462.         HLock(editor);
  1463.         BlockMove((Ptr)&pair->editor[1], (Ptr)*editor, length);
  1464.         HUnlock(editor);
  1465.         Str255 editorName;
  1466.         editorName[0] = pair->name.theText[0];
  1467.         BlockMove((Ptr)&pair->name.theText[1], (Ptr)&editorName[1], editorName[0]);
  1468.  
  1469.         if (seedFSSPtr != kODNULL && seedFSSPtr->name[0] != 0)
  1470.         {
  1471.             *theDocument = *seedFSSPtr;
  1472.         }
  1473.         else
  1474.         {
  1475.             // Create the stationery seed.  Note: this file is NOT user visible!
  1476.             // I.e. Don't have a cow about the hard coded string.
  1477.             CreateUniqueTmpFolderForFile(theDocument, "\pStationery Seed");
  1478.             FSpCreateResFile(theDocument,kODShellSignature,kODShellSignature,smSystemScript);
  1479.             CHECK(ResError());
  1480.             if (seedFSSPtr != kODNULL)
  1481.                 *seedFSSPtr = *theDocument;
  1482.         }
  1483.         
  1484.     // Plant the 'seed' resource
  1485.         saveResFile = CurResFile();
  1486.         ODSShort    seedRefNum;
  1487.         seedRefNum = FSpOpenResFile(theDocument,fsRdWrPerm);
  1488.         CHECK(ResError());
  1489.         
  1490.         AddResource(editor, kDocSeedResType, Unique1ID(kDocSeedResType), editorName);
  1491.         err= ResError();
  1492.         CloseResFile(resRefNum);
  1493.         UseResFile(saveResFile);
  1494.     }
  1495.  
  1496.     for (pair = editorUsrStrgPairs;
  1497.         pair;)
  1498.     {
  1499.         EditorUserStringList* nextPair = pair->next;
  1500.         DisposePtr( (Ptr)pair );
  1501.         pair = nextPair;
  1502.     }
  1503.     return err;
  1504. }
  1505.  
  1506. //==============================================================================
  1507. // string stuff
  1508. //==============================================================================
  1509.  
  1510. static char ODXmemcmp(char* buffer1,char* buffer2,unsigned int len)
  1511. {
  1512.   while (len-- > 0)
  1513.       if (*buffer1++ != *buffer2++)
  1514.           return (*--buffer1)-(*--buffer2);
  1515.   return 0;
  1516. }
  1517.  
  1518. static size_t    ODXstrlen(const char *s)
  1519. {
  1520.     size_t len = 0;
  1521.     while (*s++) ++len;
  1522.     return len;
  1523. }
  1524.  
  1525. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n)
  1526. {
  1527.     char* ret = destStr;
  1528.     while (n-- > 0)
  1529.         if ((*destStr++ = *srcStr++) == 0)
  1530.         {
  1531.             while (n-- > 0)
  1532.                 *destStr++ = '\0';
  1533.                 
  1534.             break;
  1535.         }
  1536.         
  1537.     return ret;    
  1538. }
  1539.  
  1540. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n)
  1541. {
  1542.     size_t len = ODXstrlen(destStr);
  1543.     destStr += len;
  1544.     return ODXstrncpy(destStr, srcStr, n);
  1545. }
  1546.  
  1547.  
  1548. //==============================================================================
  1549. // Launching the document process
  1550. //==============================================================================
  1551.  
  1552. //==============================================================================
  1553. // LaunchDocumentStub
  1554. //==============================================================================
  1555.  
  1556. OSErr LaunchDocumentStub(AEDesc* theDocument, FSSpec *documentStub,
  1557.         AEDesc* theAlias, AEDescList* otherParams, ProcessSerialNumber *psn,
  1558.         DescType eventID)
  1559. {
  1560.     
  1561.     ODUnused(otherParams);
  1562.     
  1563.     LaunchParamBlockRec    launchPB;
  1564.     OSErr                err;
  1565.  
  1566.     launchPB.launchBlockID = extendedBlock;
  1567.     launchPB.launchEPBLength = extendedBlockLen;
  1568.     launchPB.launchControlFlags = launchContinue | launchNoFileFlags;
  1569.     launchPB.launchAppSpec = documentStub;
  1570.  
  1571.     AEDesc launchDesc = {typeNull, NULL};
  1572.     AEDescList theList = {typeNull, NULL};
  1573.     AppleEvent theEvent = {typeNull, NULL};
  1574.     AEDesc myAddress;
  1575.     myAddress.descriptorType = nil;
  1576.     myAddress.dataHandle = nil;
  1577.     
  1578.     CHECK(AECreateAppleEvent(kCoreEventClass, eventID, &myAddress,
  1579.                         kAutoGenerateReturnID, kAnyTransactionID, &theEvent));
  1580. //    if (otherParams)
  1581. //        CHECK(AEPutParamDesc(&theEvent, kKeySpecialParams, otherParams));
  1582.  
  1583.     CHECK(AECreateList(nil,0,false,&theList));
  1584.     if (theAlias)
  1585.         CHECK(AEPutDesc(&theList, 0, theAlias));
  1586.     else
  1587.         CHECK(AEPutDesc(&theList, 0, theDocument));
  1588.     CHECK(AEPutParamDesc(&theEvent, keyDirectObject, &theList));
  1589.  
  1590.     CHECK(AECoerceDesc(&theEvent, typeAppParameters, &launchDesc));
  1591. /*
  1592.     This may look a little weird, since we're actually moving the event out of the
  1593.     AppParameters descriptor.  But it's necessary, the coercison to typeAppParameters
  1594.     takes the 'aevt' and puts it all in one handle, instead of
  1595.     leaving it as a AEDesc.  So, only one handle is being added to
  1596.     the launch parameter block instead of an AEDesc.
  1597. */
  1598.     HLock(launchDesc.dataHandle);
  1599.     launchPB.launchAppParameters = (AppParametersPtr)*(launchDesc.dataHandle);
  1600.  
  1601. #if defined(powerc) || defined(__powerc)
  1602. #else
  1603.     FlushInstructionCache();
  1604.     FlushDataCache();
  1605. #endif
  1606.  
  1607.     err= LaunchApplication(&launchPB);
  1608.     
  1609.     if (psn)
  1610.         *psn = launchPB.launchProcessSN;
  1611.     
  1612.     AEDisposeDesc( &launchDesc );
  1613.     AEDisposeDesc( &theList );
  1614.     AEDisposeDesc( &theEvent );
  1615.     
  1616.     return err;
  1617. }
  1618.  
  1619.  
  1620. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2)
  1621. {
  1622.     if (str1[0] != str2[0])
  1623.         return kODFalse;
  1624.     for (int i = 1; i <= str1[0]; i++)
  1625.     {
  1626.         if (str1[i] != str2[i])
  1627.             return kODFalse;
  1628.     }
  1629.     return kODTrue;
  1630. }
  1631.  
  1632.  
  1633. /*
  1634. **    Apple Macintosh Developer Technical Support
  1635. **
  1636. **    File:    GetLocalPaths.c
  1637. **
  1638. **    by Jim Luther, Apple Developer Technical Support
  1639. **
  1640. **    Copyright © 1995 Apple Computer, Inc.
  1641. **    All rights reserved.
  1642. */
  1643.  
  1644.  
  1645. pascal    OSErr    GetLocalPaths(FSSpec *spec,
  1646.                               ForkType fork,
  1647.                               unsigned long *refNumCount,
  1648.                               RefNumPtr *refNums)
  1649. {
  1650.     enum
  1651.     {
  1652.         kMaxFCBs = 348    /* The maximum number of local access paths under System 7 */
  1653.     };
  1654.     
  1655.     OSErr        result;
  1656.     FCBPBRec    pb;
  1657.     short        index;
  1658.     Str31        tempName;
  1659.     RefNumPtr    tempRefNums;
  1660.     
  1661.     /* initialize returned values */
  1662.     *refNumCount = 0;
  1663.     *refNums = NULL;
  1664.     
  1665.     /* Allocate temp storage for refNum matches */
  1666.     tempRefNums = (RefNumPtr)NewPtr(kMaxFCBs * sizeof(short));
  1667.     
  1668.     if ( tempRefNums != NULL )
  1669.     {
  1670.         /* Get FCB name in tempName */
  1671.         pb.ioNamePtr = tempName;
  1672.         
  1673.         /* Index through the open paths on the volume specified by spec->vRefNum */
  1674.         pb.ioVRefNum = spec->vRefNum;
  1675.         index = 1;
  1676.         do
  1677.         {
  1678.             pb.ioRefNum = 0;
  1679.             pb.ioFCBIndx = index;
  1680.             result = PBGetFCBInfoSync(&pb);
  1681.             if ( result == noErr )
  1682.             {
  1683.                 /*
  1684.                 **    See if parent directory ID matches and
  1685.                 **    file name matches and
  1686.                 **    the file fork (resource or data) matches
  1687.                 */
  1688.                 if ( (pb.ioFCBParID == spec->parID) &&
  1689.                      EqualString(spec->name, tempName, false, true) &&
  1690.                      ((fork == kResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1691.                 {
  1692.                     /* It's a match - add it to the array of matches */
  1693.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1694.                     ++(*refNumCount);
  1695.                 }
  1696.                 ++index;    /* next FCB index */
  1697.             }
  1698.         } while ( result == noErr );
  1699.         
  1700.         /* These errors are OK - they mean we hit the end of the FCB list */
  1701.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1702.         {
  1703.             result = noErr;
  1704.         }
  1705.         
  1706.         if ( (result == noErr) && (*refNumCount != 0) )
  1707.         {
  1708.             /* Allocate memory to return refNum matches in */
  1709.             *refNums = (RefNumPtr)NewPtr(*refNumCount * sizeof(short));
  1710.             if ( *refNums != NULL )
  1711.             {
  1712.                 /* Move refNums from tempRefNums to *refNums */
  1713.                 BlockMoveData((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1714.             }
  1715.             else
  1716.             {
  1717.                 /* Couldn't allocate memory for refNum array */
  1718.                 result = memFullErr;
  1719.             }
  1720.         }
  1721.         
  1722.         /* Free up tempRefNums storage */ 
  1723.         DisposePtr((Ptr)tempRefNums);
  1724.     }
  1725.     else
  1726.     {
  1727.         /* Couldn't allocate temp memory */
  1728.         result = memFullErr;
  1729.     }
  1730.     
  1731.     return ( result );
  1732. }
  1733.  
  1734. //------------------------------------------------------------------------------
  1735. // GetEditorUserStringPairs
  1736. //------------------------------------------------------------------------------
  1737.  
  1738. OSErr GetEditorUserStringPairs(ODSShort resRefNum, 
  1739.                             EditorUserStringList** pairs, ODUShort* editorCount)
  1740. {
  1741.     Handle         theEdtrUSnmap = kODNULL;
  1742.     *editorCount = 0;
  1743.     ODError result = noErr;
  1744.     
  1745.     if( resRefNum != -1 ) {
  1746.         ODSShort nmapCount = Count1Resources( kODNameMappings );
  1747.         if ((result = ResError()) != noErr)
  1748.             return result;
  1749.             
  1750.         for (short i=1; i<=nmapCount; i++) 
  1751.         {
  1752.                 // Get the Resource
  1753.             ODHandle nmap = (ODHandle)Get1IndResource(kODNameMappings, i);
  1754.             if ((result = ResError()) != noErr)
  1755.                 return result;
  1756.             
  1757.             if ( nmap != nil && !result  )
  1758.             {
  1759.                 HLock((ODHandle) nmap);
  1760.  
  1761.                 result = GetEditorSetFromNMAP(nmap, pairs, editorCount);
  1762.                                          
  1763.                 ReleaseResource( nmap );
  1764.             }
  1765.             
  1766.             if ((*editorCount > 0) || (result != 0))
  1767.                 break;
  1768.         }
  1769.     }
  1770.     return result;
  1771. }
  1772.  
  1773. //------------------------------------------------------------------------------
  1774. // GetEditorSetFromNMAP
  1775. //------------------------------------------------------------------------------
  1776.  
  1777. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, 
  1778.                                                          ODUShort* editorCount )
  1779. {
  1780.     ODISOStr        nameSpaceName = kODNULL; ODVolatile(nameSpaceName);
  1781.     ODUShort        nameLen;
  1782.     ODUShort        editorLen;
  1783.     ODSize            bufferPos=(ODSize)*nmap;
  1784.     ODSize            sizeShort = sizeof(ODUShort);
  1785.     OSErr            result = noErr;
  1786.     
  1787.     BlockMove((ODPtr)bufferPos, (ODPtr)&nameLen, sizeShort);
  1788.     bufferPos += sizeShort;
  1789.  
  1790.     nameSpaceName = (ODISOStr)NewPtrClear((ODSize)nameLen+1);
  1791.     if (!nameSpaceName)
  1792.         result = memFullErr;
  1793.     else
  1794.     {
  1795.         BlockMove((ODPtr)bufferPos, (ODPtr)nameSpaceName, (ODSize)nameLen);
  1796.         bufferPos += (ODSize)nameLen;
  1797.         
  1798.         if (!ODXmemcmp(nameSpaceName,kODEditorUserString,ODXstrlen(kODEditorUserString)))
  1799.         {
  1800.             BlockMove((ODPtr)bufferPos,(ODPtr)editorCount, sizeShort);
  1801.             bufferPos += sizeShort;
  1802.             
  1803.             if ( *editorCount > 0 )
  1804.             {
  1805.     
  1806.                 *pairs = (EditorUserStringList*)NewPtrClear(
  1807.                                               sizeof(EditorUserStringList));
  1808.                 if (!*pairs)
  1809.                     result = memFullErr;
  1810.                 else
  1811.                 {
  1812.                     EditorUserStringList* thisPair = *pairs;
  1813.                     
  1814.                     for(ODUShort i=0; i < *editorCount && thisPair; i++)
  1815.                     {
  1816.                         BlockMove((ODPtr)bufferPos,(ODPtr)&editorLen,sizeShort);
  1817.                         bufferPos += sizeShort;
  1818.                         
  1819.                         thisPair->editor[0] = editorLen;
  1820.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->editor[1],
  1821.                                                          (ODSize)editorLen);
  1822.                         bufferPos += (ODSize)editorLen;
  1823.                         bufferPos += sizeShort;
  1824.                                         
  1825.                             // read UserString from the nmap
  1826.                         BlockMove((ODPtr)bufferPos, 
  1827.                             (ODPtr)&thisPair->name.theScriptCode,sizeof(ScriptCode));
  1828.                         bufferPos += sizeof(ScriptCode);
  1829.                         BlockMove((ODPtr)bufferPos, 
  1830.                             (ODPtr)&thisPair->name.theLangCode,sizeof(LangCode));
  1831.                         bufferPos += sizeof(LangCode);
  1832.                         BlockMove((ODPtr)bufferPos,(ODPtr)&nameLen,sizeShort);
  1833.                         bufferPos += sizeShort;
  1834.                         thisPair->name.theText[0] = nameLen;
  1835.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->name.theText[1], nameLen);
  1836.                         bufferPos += nameLen;
  1837.                         
  1838.                         if (i+1 < *editorCount )
  1839.                         {
  1840.                             thisPair->next = (EditorUserStringList*)NewPtrClear(
  1841.                                               sizeof(EditorUserStringList));
  1842.                             thisPair = thisPair->next;
  1843.                             if (!thisPair)
  1844.                                 result = memFullErr;
  1845.  
  1846.                         }
  1847.                     }
  1848.                 }
  1849.             }
  1850.         }
  1851.     }
  1852.  
  1853.     DisposePtr(nameSpaceName);
  1854.     return result;
  1855. }
  1856.  
  1857. //------------------------------------------------------------------------------
  1858. // MoveToTrash -- $$$$$ duplicated from Prefs.cpp
  1859. //------------------------------------------------------------------------------
  1860. static void
  1861. MoveToTrash( short vRefnum, long dirID, Str255 name )
  1862. {
  1863.     short foundVRefNum;
  1864.     long  foundDirID;
  1865.     
  1866.     if(!FindFolder(vRefnum, kTrashFolderType, kDontCreateFolder, 
  1867.                                 &foundVRefNum, &foundDirID))
  1868.     {
  1869.  
  1870.         CMovePBRec paramBlock ;
  1871.         memset( ¶mBlock, 0, sizeof(paramBlock) );
  1872.         
  1873.         paramBlock.ioNamePtr = name ;
  1874.         paramBlock.ioVRefNum = foundVRefNum ;
  1875.         paramBlock.ioNewDirID = foundDirID ;
  1876.         paramBlock.ioDirID = dirID ;
  1877.         
  1878.         (void) HDelete(foundVRefNum,foundDirID,name);     // ignore error (may not exist)
  1879.         OSErr result = PBCatMoveSync( ¶mBlock );
  1880.         if (result)
  1881.             (void) HDelete(vRefnum,dirID,name); 
  1882.     }
  1883.     else
  1884.         (void) HDelete(vRefnum,dirID,name); 
  1885. }
  1886.  
  1887.  
  1888. //------------------------------------------------------------------------------
  1889. // ShowAboutScreen
  1890. //------------------------------------------------------------------------------
  1891.  
  1892. static short    GetMainDeviceDepth( ODBoolean *isColor )
  1893. {
  1894.     GDHandle        device;
  1895.     short            depth;
  1896.     PixMapHandle    pmap;
  1897.     
  1898.     depth  = 1;
  1899.     *isColor = kODTrue;
  1900.     device = GetMainDevice();
  1901.     if (
  1902.         (TestDeviceAttribute(device, screenDevice)) &&
  1903.         (TestDeviceAttribute(device, screenActive))
  1904.     ) {
  1905.         pmap  = (*device)->gdPMap;
  1906.         depth = (*pmap)->pixelSize;
  1907.         *isColor = TestDeviceAttribute(device,gdDevType);
  1908.     }
  1909.     
  1910.     return(depth);
  1911. }
  1912.  
  1913. const short kSplashDlogID            = kODSplashDlogID;
  1914. const short kSplashDefaultPICTID    = 131;
  1915. const short kSplashBWPICTID            = 132;
  1916. const short kSplash16GrayPICTID        = 133;
  1917. const short kSplashBestPICTID        = 134;
  1918.  
  1919.  
  1920. DialogPtr ShowAboutScreen( )
  1921. {
  1922.     DialogPtr aboutScreen = NULL;
  1923.     Boolean color;
  1924.     short depth = GetMainDeviceDepth(&color);
  1925.     
  1926.     short pictID = kSplashDefaultPICTID;
  1927.  
  1928.     Str255 s255; s255[0]=0;
  1929.     WindowPtr ww = FrontWindow();
  1930.     if (ww)
  1931.         GetWTitle(ww, s255);
  1932.     else
  1933.         BlockMove(LMGetCurApName(), s255, 32);
  1934.         
  1935.     if (!EqualString(s255, "\pAbout OpenDoc...", TRUE, FALSE))
  1936.                     // Note, the above string is NEVER user visible, so there is no need
  1937.                     // to worry about localizing it.
  1938.         if( !color && depth>=4 )
  1939.             pictID = kSplash16GrayPICTID;    // Use grayscale
  1940.         else if( depth>=8 )
  1941.             pictID = kSplashBestPICTID;        // Use 8-bit color
  1942.         else
  1943.             pictID = kSplashBWPICTID;        // Use black-and-white
  1944.     
  1945.     if( Get1Resource('DLOG',kSplashDlogID) )
  1946.         aboutScreen = GetNewDialog(kSplashDlogID,NULL,(WindowPtr)-1L);
  1947.     if( aboutScreen ) {
  1948.         short        itemHit;
  1949.         Handle        scratchHandle = kODNULL;
  1950.         Rect        itemRect;
  1951.     
  1952.         GetDialogItem(aboutScreen, 1, &itemHit, &scratchHandle, &itemRect);
  1953.         
  1954.         PicHandle pictHandle = (PicHandle)Get1Resource('PICT', pictID);
  1955.         
  1956.         TEHandle te = ((DialogPeek)aboutScreen)->textH;
  1957.         (**te).just = teJustCenter;
  1958.         
  1959. #if PRAGMA_ALIGN_SUPPORTED
  1960. #pragma options align=mac68k
  1961. #endif
  1962.  
  1963.         struct VersRsrc {
  1964.             long    versJunk;
  1965.             short    region;
  1966.             Str255    versionStr;
  1967.         };
  1968.  
  1969. #if PRAGMA_ALIGN_SUPPORTED
  1970. #pragma options align=reset
  1971. #endif
  1972.  
  1973.         VersRsrc **vers = (VersRsrc**) Get1Resource('vers',2);
  1974.         if( vers ) {
  1975.             HLock((Handle)vers);
  1976.             ParamText((**vers).versionStr,NULL,NULL,NULL);
  1977.             ReleaseResource((Handle)vers);
  1978.         } else
  1979.             ParamText("\p????",NULL,NULL,NULL);
  1980.         
  1981.         ShowWindow(aboutScreen);
  1982.         SelectWindow(aboutScreen);
  1983.         DrawDialog(aboutScreen);
  1984.         SetPort(aboutScreen);
  1985.         if (pictHandle)
  1986.         {
  1987.             HLock((Handle)pictHandle);
  1988.             DrawPicture(pictHandle, &itemRect);
  1989.             HUnlock((Handle)pictHandle);
  1990.             ReleaseResource((Handle)pictHandle);
  1991.         }
  1992.  
  1993.         ValidRect(&aboutScreen->portRect);
  1994.     }
  1995.     return aboutScreen;
  1996. }
  1997.  
  1998. //------------------------------------------------------------------------------
  1999. // IsSystem753OrGreater
  2000. //------------------------------------------------------------------------------
  2001.  
  2002. ODBoolean IsSystem753OrGreater()
  2003. {
  2004.     return IsCertainSystemVersionOrGreater(0x753);
  2005. }
  2006.  
  2007. //------------------------------------------------------------------------------
  2008. // IsSystem8OrGreater
  2009. //------------------------------------------------------------------------------
  2010.  
  2011. ODBoolean IsSystem8OrGreater()
  2012. {
  2013.     return IsCertainSystemVersionOrGreater(0x800);
  2014. }
  2015.  
  2016. //------------------------------------------------------------------------------
  2017. // IsCertainSystemVersionOrGreater
  2018. //------------------------------------------------------------------------------
  2019.  
  2020. ODBoolean IsCertainSystemVersionOrGreater(long systemVersion)
  2021. {
  2022.     long    response;
  2023.  
  2024.     OSErr error = Gestalt(gestaltSystemVersion, &response);
  2025.     return LoWord(response) >= systemVersion;
  2026.     if (error)
  2027.         ODPrcsDebugStr("IsCertainSystemVersionOrGreater: Unexpected error from Gestalt!");
  2028. }
  2029.  
  2030. //------------------------------------------------------------------------------
  2031. //    ChangeDesktopDatabase
  2032. //
  2033. //    Add/remove an app of creator kODShellSignature to/from desktop database
  2034. //    If there is a problem, it fails silently (What other recourse?)
  2035. //------------------------------------------------------------------------------
  2036.  
  2037. void ChangeDesktopDatabase(FSSpec* fileSpec, ODBoolean add)
  2038. {
  2039.     DTPBRec    pb;
  2040.     OSErr    err;
  2041.  
  2042.     // CHECK FOR AVAILABILITY OF DESKTOP MANAGER
  2043.     {
  2044.         HParamBlockRec            volParams;
  2045.         GetVolParmsInfoBuffer    info;
  2046.     
  2047.         memset(&volParams, 0, sizeof(volParams));
  2048.  
  2049.         volParams.ioParam.ioVRefNum = fileSpec->vRefNum;
  2050.         volParams.ioParam.ioBuffer = (Ptr)&info;
  2051.         volParams.ioParam.ioReqCount = sizeof(info);
  2052.  
  2053.         err = PBHGetVolParmsSync(&volParams);
  2054.         if (err || volParams.ioParam.ioReqCount != volParams.ioParam.ioActCount)
  2055.         {
  2056.             ODPrcsDebugStr("ChangeDesktopDatabase: Error calling PBHGetVolParmsSync");
  2057.             return;
  2058.         }
  2059.  
  2060.         if ( ! (info.vMAttrib & 1<<bHasDesktopMgr))
  2061.         {
  2062.             ODPrcsDebugStr("ChangeDesktopDatabase: Hey man, no desktop database available?");
  2063.             return;
  2064.         }
  2065.     }
  2066.  
  2067.     memset(&pb, 0, sizeof(pb));
  2068.  
  2069.     pb.ioNamePtr = NULL;
  2070.     pb.ioVRefNum = fileSpec->vRefNum;
  2071.     err = PBDTGetPath(&pb);
  2072.     if (err)
  2073.     {
  2074.         ODPrcsDebugStr("ChangeDesktopDatabase: Error getting reference to desktop DB");
  2075.         return;
  2076.     }
  2077.  
  2078.     pb.ioNamePtr = fileSpec->name;
  2079.     pb.ioNamePtr = fileSpec->name;
  2080.     pb.ioDirID = fileSpec->parID;
  2081.     pb.ioFileCreator = kODShellSignature;
  2082.     
  2083.     if (add)
  2084.     {
  2085.         err = PBDTAddAPPLSync(&pb);
  2086.         if (err)
  2087.         {
  2088.             ODPrcsDebugStr("ChangeDesktopDatabase: Error adding APPL");
  2089.             return;
  2090.         }
  2091.     }
  2092.     else
  2093.     {
  2094.         // DON'T CARE AT ALL ABOUT ERRORS HERE.
  2095.         err = PBDTRemoveAPPLSync(&pb);
  2096.         if (err)
  2097.             return;
  2098.     }
  2099.  
  2100.     (void) PBDTFlushSync(&pb);
  2101. }
  2102. #if 0 /* LAUNCHER CAN'T USE EXCEPTION HANDLING. I SHOULD ADD THIS IN THOUGH. */
  2103. //------------------------------------------------------------------------------
  2104. //    EnableApp
  2105. //------------------------------------------------------------------------------
  2106.  
  2107. void EnableApp(FSSpec* fileSpec)
  2108. {
  2109.     TRY
  2110.         TempPlatformFile    file = new PlatformFile;
  2111.         
  2112.         file->Specify(fileSpec);
  2113.         
  2114.         file->SetPlatformCreator(kODShellSignature);
  2115.         ChangeDesktopDatabase(fileSpec, kODAppAPPL);
  2116.     CATCH_ALL
  2117.     ENDTRY
  2118. }
  2119.  
  2120. //------------------------------------------------------------------------------
  2121. //    DisableApp
  2122. //------------------------------------------------------------------------------
  2123.  
  2124. void EnableApp(FSSpec* fileSpec)
  2125. {
  2126.     TRY
  2127.         TempPlatformFile    file = new PlatformFile;
  2128.         
  2129.         file->Specify(fileSpec);
  2130.         
  2131.         file->SetPlatformCreator(kODShellSignature);
  2132.         ChangeDesktopDatabase(fileSpec, kODAppAPPL);
  2133.     CATCH_ALL
  2134.     ENDTRY
  2135. }
  2136. #endif
  2137. //------------------------------------------------------------------------------
  2138. // GetOpenDocLibsFolderInfo
  2139. //
  2140. //    Return directory ID of the OpenDoc Libraries folder. This ID can be used
  2141. //    to find items INSIDE this folder. It is NOT the ID of the folder's parent.
  2142. //------------------------------------------------------------------------------
  2143.  
  2144. OSErr GetOpenDocLibsFolderInfo(long* dirID, short* vRefNum)
  2145. {
  2146.     long        libsFldrDirID;
  2147.     short        libsFldrVRefNum;
  2148.     Str255        folderName;
  2149.     OSErr        result = noErr;
  2150.  
  2151.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  2152.  
  2153.     if (folderName[0] == 0)
  2154.         ODPrcsDebugStr("Resource Error: OpenDoc Libraries string not found!");
  2155.     
  2156.     result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  2157.                                 kDontCreateFolder, &libsFldrVRefNum, 
  2158.                                 &libsFldrDirID);
  2159.             
  2160.     if (result == noErr)
  2161.     {
  2162.         CInfoPBRec        CinfoPB;
  2163.  
  2164.         memset (&CinfoPB, 0 ,sizeof(CinfoPB));
  2165.  
  2166.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  2167.         CinfoPB.dirInfo.ioFDirIndex = 0;
  2168.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  2169.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  2170.         
  2171.         result = PBGetCatInfoSync(&CinfoPB);
  2172.         if (result == noErr)
  2173.         {
  2174.             
  2175.  
  2176.             *dirID = CinfoPB.dirInfo.ioDrDirID;
  2177.             *vRefNum = libsFldrVRefNum;
  2178.         }
  2179.     }
  2180.     
  2181.     return result;
  2182. }
  2183.  
  2184. //------------------------------------------------------------------------------
  2185. // FindODLibFileWithSignature
  2186. //
  2187. //    Given the dirID and vRefNum of the OpenDoc Libraries folder, find a file
  2188. //    with a particular signature.
  2189. //
  2190. //    Result is returned in fileName.
  2191. //------------------------------------------------------------------------------
  2192.  
  2193. OSErr FindODLibFileWithSignature(Str255 fileName,
  2194.                                     short vRefNum,
  2195.                                     long dirID,
  2196.                                     OSType signature)
  2197. {
  2198.     OSErr        error;
  2199.     CInfoPBRec    catInfo;
  2200.  
  2201.     // LOOP THROUGH ALL THE FILES IN THE FOLDER
  2202.     memset (&catInfo, 0, sizeof(catInfo));
  2203.     catInfo.dirInfo.ioNamePtr = fileName;
  2204.     catInfo.dirInfo.ioFDirIndex = 1;
  2205.     catInfo.dirInfo.ioVRefNum = vRefNum;
  2206.     catInfo.dirInfo.ioDrDirID = dirID;
  2207.  
  2208.     for(error = PBGetCatInfoSync(&catInfo); 
  2209.                     error == noErr; 
  2210.                    error = PBGetCatInfoSync(&catInfo))
  2211.     {
  2212.         // if this is a folder
  2213.         if ((catInfo.dirInfo.ioFlAttrib & (1<<4))) 
  2214.         {
  2215.             // IGNORE IT
  2216.         }
  2217.         else
  2218.         {
  2219.             // if this is an alias
  2220.             if ((catInfo.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  2221.             {
  2222.                 // IGNORE IT
  2223.             }
  2224.             else
  2225.             {
  2226.                 FInfo    fileInfo;
  2227.                 FSSpec    fileSpec;
  2228.  
  2229.                 CopyPascalString(fileSpec.name, fileName);
  2230.                 fileSpec.parID = dirID;
  2231.                 fileSpec.vRefNum = vRefNum;
  2232.                 error = FSpGetFInfo(&fileSpec, &fileInfo);
  2233.                 if (!error && fileInfo.fdCreator == signature)
  2234.                 {
  2235.                     error = noErr;
  2236.                     break;
  2237.                 }
  2238.             }
  2239.         }
  2240.  
  2241.         catInfo.hFileInfo.ioFDirIndex++;
  2242.         //need to do this each time since PBGetCatInfo call returns val here
  2243.         catInfo.hFileInfo.ioNamePtr = fileName;
  2244.         catInfo.hFileInfo.ioVRefNum = vRefNum;
  2245.         catInfo.hFileInfo.ioDirID = dirID;  
  2246.     }
  2247.  
  2248.     return error;
  2249. }
  2250.  
  2251. //------------------------------------------------------------------------------
  2252. //    RunningUnderMacOS8
  2253. //------------------------------------------------------------------------------
  2254.  
  2255. ODBoolean RunningUnderMacOS8()
  2256. {
  2257.     Str255    errorString;
  2258.  
  2259.     if (IsSystem8OrGreater())
  2260.     {
  2261.         GetIndString(errorString, kSHLMiscErrorStringsStrID,
  2262.                                     kSHLCannotRunUnderMacOS8Index);
  2263.         ReportErrorGeneric(errorString);
  2264.         return kODTrue;
  2265.     }
  2266.     return kODFalse;
  2267. }
  2268.  
  2269. //==============================================================================
  2270. // NEW PREFS RESOURCE (odst) INTERFACE
  2271. //==============================================================================
  2272.  
  2273. // I WANTED TO PUT THESE IN THE HEADER FOR THE CLASS, BUT THE COMPILER
  2274. //    COMPLAINED.
  2275.  
  2276. const OSType        kSetupPrefsResourceType = 'odst';
  2277. const short            kSetupPrefsResourceID = 0;
  2278. const Boolean        kRunAtSysStartupDefault = 0;
  2279. const Boolean        kRunTilSysShutdownDefault = 0;
  2280. const long            kLatestVersion = 0;
  2281.  
  2282. //------------------------------------------------------------------------------
  2283. //    ODSetUpPrefs::ODSetUpPrefs
  2284. //------------------------------------------------------------------------------
  2285.  
  2286. ODSetUpPrefs::ODSetUpPrefs(short refNum, short permissions)
  2287. {
  2288.     if (refNum < 0)
  2289.     {
  2290.         fRefNum = OpenODPrefsResFile(true, fsRdWrPerm);
  2291.         if (fRefNum < 0)
  2292.         {
  2293.             fRefNum = OpenODPrefsResFile(true, fsRdPerm);
  2294.             fPermissions = fsRdPerm;
  2295.         }
  2296.         else
  2297.             fPermissions = fsRdWrPerm;
  2298.         fOpenedFileMyself = true;
  2299.     }
  2300.     else
  2301.     {
  2302.         fRefNum = refNum;
  2303.         fPermissions = permissions;
  2304.         fOpenedFileMyself = false;
  2305.     }
  2306.     
  2307.     fResource = (ODSetupPrefsResourceH)Get1Resource(kSetupPrefsResourceType,
  2308.                                                     kSetupPrefsResourceID);
  2309.     if (!fResource)
  2310.     {
  2311.         // USE DEFAULTS AND MAKE BRAND NEW RESOURCE
  2312.         fRunAtSysStartup = kRunAtSysStartupDefault;
  2313.         fRunTilSysShutdown = kRunTilSysShutdownDefault;
  2314.  
  2315.         fResource = (ODSetupPrefsResourceH)NewHandle(
  2316.                                                 sizeof(ODSetupPrefsResource));
  2317.         if (fResource)
  2318.         {
  2319.             (**fResource).runAtSysStartup = fRunAtSysStartup;
  2320.             (**fResource).runTilSysShutdown = fRunTilSysShutdown;
  2321.             (**fResource).version = kLatestVersion;
  2322.             AddResource((Handle)fResource, kSetupPrefsResourceType,
  2323.                         kSetupPrefsResourceID, "\p");
  2324.             WriteResource((Handle)fResource);
  2325.         }
  2326.     }
  2327.     else
  2328.     {
  2329.         // READ DATA FROM RESOURCE
  2330.         fRunAtSysStartup = (**fResource).runAtSysStartup;
  2331.         fRunTilSysShutdown = (**fResource).runTilSysShutdown;
  2332.     }
  2333. }
  2334.  
  2335. //------------------------------------------------------------------------------
  2336. //    ODSetUpPrefs::~ODSetUpPrefs
  2337. //------------------------------------------------------------------------------
  2338.  
  2339. ODSetUpPrefs::~ODSetUpPrefs()
  2340. {
  2341.     if (fOpenedFileMyself)
  2342.         CloseResFile(fRefNum);
  2343. }
  2344. #if 0
  2345. //------------------------------------------------------------------------------
  2346. //    ODSetUpPrefs::GetRunAtSysStartup
  2347. //------------------------------------------------------------------------------
  2348.  
  2349. Boolean    ODSetUpPrefs::GetRunAtSysStartup()
  2350. {
  2351.     return fRunAtSysStartup;
  2352. }
  2353. #endif /* 0 */
  2354. //------------------------------------------------------------------------------
  2355. //    ODSetUpPrefs::GetRunTilSysShutdown
  2356. //------------------------------------------------------------------------------
  2357.  
  2358. Boolean    ODSetUpPrefs::GetRunTilSysShutdown()
  2359. {
  2360.     return fRunTilSysShutdown;
  2361. }
  2362. #if 0
  2363. //------------------------------------------------------------------------------
  2364. //    ODSetUpPrefs::SetRunAtSysStartup
  2365. //------------------------------------------------------------------------------
  2366.  
  2367. OSErr ODSetUpPrefs::SetRunAtSysStartup(Boolean runAtSysStartup)
  2368. {
  2369.     OSErr    error;
  2370.  
  2371.     if (fPermissions == fsRdPerm)
  2372.         error = fLckdErr;
  2373.     else
  2374.     {
  2375.         (**fResource).runAtSysStartup = runAtSysStartup;
  2376.         error = this->UpdateFile();
  2377.         if (!error)
  2378.             fRunAtSysStartup = runAtSysStartup;
  2379.     }
  2380.     return error;
  2381. }
  2382. #endif /* 0 */
  2383. //------------------------------------------------------------------------------
  2384. //    ODSetUpPrefs::SetRunTilSysShutdown
  2385. //------------------------------------------------------------------------------
  2386.  
  2387. OSErr ODSetUpPrefs::SetRunTilSysShutdown(Boolean runTilSysShutdown)
  2388. {
  2389.     OSErr    error;
  2390.  
  2391.     if (fPermissions == fsRdPerm)
  2392.         error = fLckdErr;
  2393.     else
  2394.     {
  2395.         (**fResource).runTilSysShutdown = runTilSysShutdown;
  2396.         error = this->UpdateFile();
  2397.         if (!error)
  2398.             fRunTilSysShutdown = runTilSysShutdown;
  2399.     }
  2400.     return error;
  2401. }
  2402.  
  2403. //------------------------------------------------------------------------------
  2404. //    ODSetUpPrefs::UpdateFile
  2405. //------------------------------------------------------------------------------
  2406.  
  2407. OSErr ODSetUpPrefs::UpdateFile()
  2408. {
  2409.     OSErr    error;
  2410.  
  2411.     ChangedResource((Handle)fResource);
  2412.     error = ResError();
  2413.     if (!error)
  2414.     {
  2415.         WriteResource((Handle)fResource);
  2416.         error = ResError();
  2417.     }
  2418.     return error;
  2419. }
  2420.  
  2421. //------------------------------------------------------------------------------
  2422. //    ODSetUpPrefs::GetDefaultSize
  2423. //------------------------------------------------------------------------------
  2424.  
  2425. OSErr ODSetUpPrefs::GetDefaultSize(Size& size)
  2426. {
  2427.     return GetODDefaultSize(fRefNum, size);
  2428. }
  2429.  
  2430. //------------------------------------------------------------------------------
  2431. //    ODSetUpPrefs::SetDefaultSize
  2432. //------------------------------------------------------------------------------
  2433.  
  2434. OSErr ODSetUpPrefs::SetDefaultSize(Size newSize)
  2435. {
  2436.     return SetODDefaultSize(fRefNum, newSize);
  2437. }
  2438.  
  2439.